﻿// -----------------------------------------------------------------------
// <copyright file="WriterReader.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace logika
{
    using System.IO;
    using System.Windows.Forms;
    using System.Collections.Generic;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class WriterReader
    {
        private Node root;
        private int count = 1;
        public List<string> children;
        public string tree;
        public List<string> properTree;
        private int poziom = 1;
        private int liczbaPoziomow = 1;
        private StreamWriter writer;

        public int Save(Node root, string file = null)
        {
            this.root = root;
            this.poziom = 0;
            this.children = new List<string>();

            oneCycle();
            //this.WriteToFile(file);
            int tmp = this.poziom;
            this.poziom = 1;
            for (int i = 1; i < tmp; i++)
            {
                this.poziom++;
                oneCycle();
                //this.WriteNextTree(file);
                this.WriteToFile(file + i.ToString() + ".tre");
                this.WriteEndOfFile(file + i.ToString() + ".tre");
            }
            return tmp;
        }

        private void oneCycle()
        {
            this.liczbaPoziomow = 1;
            this.children.Clear();
            this.tree = "(1:" + root.wiek.ToString() + ",";
           // this.children.Add(this.poziom.ToString() + "1_" + root.sekwencja);
            this.CountNodes(this.root, 0);
            this.tree += ");";
            this.count = children.Count;
        }

        public void CountNodes(Node cursor, int wiek, int aktualny_poziom = 1)
        {
            children.Add(aktualny_poziom.ToString() + children.Count.ToString() + "_" + cursor.sekwencja);
            if ((cursor.potomne.Count == 0) || (aktualny_poziom == this.poziom))
            {
                this.tree += (children.Count/*properTree.IndexOf(cursor.sekwencja)*/).ToString() + ":" + (cursor.wiek - wiek).ToString();
                if (aktualny_poziom == this.poziom)
                {
                    //if (wiek != 0) this.tree += "):" + (cursor.wiek - wiek).ToString();
                }
            }
            else
            {
                int i = 0;
                foreach (Node child in cursor.potomne)
                {
                    if (child.potomne.Count != 0 && aktualny_poziom < this.poziom - 1)
                    {
                        this.tree += "(";
                        children.RemoveAt(children.Count-1);
                    }
                    CountNodes(child, cursor.wiek, aktualny_poziom + 1);
                    i++;
                    
                   if (cursor.potomne.Count != i) this.tree += ",";
                }
                if( wiek != 0 ) this.tree += "):" + (cursor.wiek - wiek).ToString();
            }
            if (aktualny_poziom > this.poziom) this.poziom = aktualny_poziom;
        }

        private StreamWriter RunSaveDialog(string file_name = null)
        {
            if (file_name == null)
            {
                SaveFileDialog sfd = new SaveFileDialog();
                sfd.FileName = "drzewo"; // Default file name
                sfd.DefaultExt = ".tre"; // Default file extension
                sfd.Filter = "Tree documents (.tre)|*.tre"; // Filter files by extension
                if (sfd.ShowDialog() != DialogResult.OK) return null;
                else file_name = sfd.FileName;
            }
            if(writer == null || writer.BaseStream == null)
                writer = new StreamWriter(file_name, false); 
            if (file_name != null)
                return writer;
            else return null;
        }

        public void WriteToFile(string file_name = null)
        {
            RunSaveDialog(file_name);
            //var writer = RunSaveDialog(file_name);

            writer.WriteLine("#NEXUS\n");
            writer.WriteLine("[File saved " + System.DateTime.Now.ToString() + "]\n");
            writer.WriteLine("BEGIN TAXA;");
            writer.Write("\tDIMENSIONS NTAX = ");
            writer.WriteLine(count.ToString() + ";");
            writer.WriteLine("\tTAXLABELS");
            string transtlate = "";
            int i = 1;
            foreach (string child in children)
            {
                writer.WriteLine("\t\t" + child);
                transtlate += "\t\t" + i.ToString() + "\t" + child;
                if (i != children.Count) transtlate += ",\n";
                else transtlate += "\n";
                i++;
            }
            transtlate += "\t\t;";
            writer.WriteLine("\t\t;\nENDBLOCK;\n\n\nBEGIN TREES;\n[!]\n\tTRANSLATE\n" + transtlate);
            writer.WriteLine("\tTREE * PAUP_1= [&U] " + this.tree);

           // writer.Close();
        }

        private void WriteNextTree(string file_name = null)
        {
            //RunSaveDialog(file_name);
            //var writer = RunSaveDialog(file_name);
            writer.WriteLine("\tTREE PAUP_" + poziom.ToString() + "= [&U] " + this.tree);
            //writer.Close();
        }

        private void WriteEndOfFile(string file_name = null)
        {
            RunSaveDialog(file_name);
            //var writer = RunSaveDialog(file_name);
            writer.WriteLine("ENDBLOCK;");
            writer.Close();
        }
        
        public void SaveStructure(Node root)
        {
            if (root == null) return;

            SaveFileDialog sfd = new SaveFileDialog();
            sfd.FileName = "drzewo"; // Default file name
            sfd.DefaultExt = ".str"; // Default file extension
            sfd.Filter = "Tree documents (.str)|*.str"; // Filter files by extension
            if (sfd.ShowDialog() == DialogResult.OK)
            {
                System.IO.StreamWriter plik = new System.IO.StreamWriter(sfd.FileName, false);
                plik.WriteLine(struktura_to_string(root));
                plik.Close();
            }
        }

        private string struktura_to_string(Node n, int start_wiek = 0)
        {
            string drzewko = "( " + n.wiek + " ";
            foreach (var p in n.potomne)
            {
                drzewko += struktura_to_string(p, start_wiek) + " ";
            }
            return drzewko + " )";
        }

        public Node ReadStructure(string file_name)
        {
            Node root = new Node("");
            List<Node> lista = new List<Node>();
            int liczba = 0;

            lista.Add(root);
            System.IO.StreamReader plik = new System.IO.StreamReader(file_name);

            while (plik.Read() != '(');
            string struktura = plik.ReadToEnd();
            plik.Close();
            
            foreach (var znak in struktura)
            {
                if (znak >= 48 && znak <= 57)
                    liczba = liczba * 10 + (znak - 48);
                else
                {
                    if (lista.Count > 0 && lista[lista.Count - 1].wiek <= 0)
                    {
                        lista[lista.Count - 1].wiek = liczba;
                        liczba = 0;
                    }
                    if (znak == '(')
                    {
                        var child = new Node("");
                        lista[lista.Count - 1].potomne.Add(child);
                        lista.Add(child);
                    }
                    if (znak == ')')
                    {
                        lista.RemoveAt(lista.Count-1);
                    }
                }
            }

            return root;
        }
    }
}
